home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / sys / unix / snd86unx.shr < prev    next >
Encoding:
Text File  |  1993-08-01  |  28.2 KB  |  1,061 lines  |  [TEXT/R*ch]

  1. # This is a shell archive.  Save it in a file, remove anything before
  2. # this line, and then unpack it by entering "sh file".  Note, it may
  3. # create directories; files and directories will be owned by you and
  4. # have default permissions.
  5. #
  6. # This archive contains:
  7. #
  8. #    READ.ME
  9. #    install.bsd
  10. #    spkr.7
  11. #    Makefile
  12. #    spkr.c
  13. #    spkr.h
  14. #    interp.c
  15. #    Files
  16. #    Install
  17. #    Master
  18. #    Name
  19. #    Node
  20. #    Remove
  21. #    Size
  22. #    System
  23. #    playtest
  24. #
  25. echo x - READ.ME
  26. sed 's/^X//' >READ.ME << 'END-of-READ.ME'
  27. X        Console Speaker Driver Package (v1.1)
  28. X
  29. X        by Eric S. Raymond (esr@snark.thyrsus.com)
  30. X
  31. XThis package gives 80386 machines running SVr3.2 or later the ability to play
  32. Xtunes on the console speaker.  It has been extended to 386BSD (and possibly
  33. XBSDI) by Andrew A. Chernov, and to SCO UNIX 3.2.4 (and possibly other VPIX
  34. Xsystems) by Andreas Arens.
  35. X
  36. XThe following files are contained in the kit:
  37. X
  38. XDocumentation and examples:
  39. XREAD.ME        -- this file
  40. Xspeaker.7    -- man page for the driver
  41. Xplaytest    -- test script exercising familiar tunes
  42. X
  43. XInstallable driver kit parts, for SVr3.2 or later:
  44. XFiles        -- list of driver package file locations
  45. XInstall        -- installation script for driver kit
  46. XMaster        -- mdevice entry for speaker driver
  47. XName        -- name entry foe speaker driver
  48. XNode        -- /dev node specification file
  49. XRemove        -- Driver removal script
  50. XSize        -- installation size data
  51. XSystem        -- sdevice entry for speaker driver
  52. X
  53. XDriver source code, for SVr3.2 or later and 386BSD:
  54. XMakefile    -- Makefile for driver code
  55. Xspkr.c        -- the driver source
  56. Xspeaker.h    -- ioctl interface file
  57. X
  58. XCommon source code:
  59. Xinterp.c    -- play string interpretation code
  60. X
  61. XFor SVr3.2 or later, simply type `make' and wait. Then type ./Install
  62. Xand follow its instructions. You will have to install the man pages by hand.
  63. XBe aware that the speaker.7 man page uses tbl(1) constructs.
  64. X
  65. XFor 386BSD, follow the installation instructions in install.bsd.
  66. X
  67. XFor SCO UNIX 3.2.4, no new kernel drivers are needed, and you need only
  68. Xcopy interp.c to your src directory and proceed with making NetHack, with
  69. XVPIX_MUSIC set in unixconf.h.
  70. X
  71. XInteresting tunes mailed to the author will be periodically posted in batches
  72. Xand added to the test script for future versions.
  73. X
  74. X            Revision notes
  75. X
  76. X1.1 -- fixed minor bug in M[LSN] interpretation, added octave-tracking.
  77. X       Tweaked the playtest examples.
  78. END-of-READ.ME
  79. echo x - install.bsd
  80. sed 's/^X//' >install.bsd << 'END-of-install.bsd'
  81. XCopy spkr.c and interp.c to /sys/i386/isa
  82. XCopy spkr.h to /sys/sys
  83. X
  84. X-----------------------------------------------------------------------------
  85. X
  86. XFile /sys/i386/conf/YOUR_MACHINE_NAME
  87. Xadd following line:
  88. X
  89. Xpseudo-device   speaker
  90. X
  91. X-----------------------------------------------------------------------------
  92. X
  93. XFile /sys/i386/conf/files.i386
  94. Xadd following line:
  95. X
  96. Xi386/isa/spkr.c         optional speaker
  97. X
  98. X-----------------------------------------------------------------------------
  99. X
  100. XFile /sys/i386/i386/conf.c
  101. X[major number 20 (hex) is registered for spkr driver, don't change it]
  102. Xadd following code:
  103. X
  104. X#include "speaker.h"
  105. X#if NSPEAKER > 0
  106. Xint     spkropen(),spkrclose(),spkrwrite(),spkrioctl();
  107. X#else
  108. X#define spkropen  enxio
  109. X#define spkrclose enxio
  110. X#define spkrwrite enxio
  111. X#define spkrioctl enxio
  112. X#endif
  113. X    ...
  114. X
  115. Xstruct cdevsw    cdevsw[] =
  116. X{
  117. X    ...
  118. X
  119. X    { spkropen,     spkrclose,      enxio,          spkrwrite,      /*20*/
  120. X      spkrioctl,    enxio,          enxio,          NULL,
  121. X      enxio,        enxio,          enxio },
  122. X    ...
  123. X
  124. X-----------------------------------------------------------------------------
  125. X
  126. XMake corresponding device:
  127. X
  128. X    mknod /dev/speaker c 32 0
  129. X
  130. X[major number 32 (20 hex) is registered for spkr driver, don't change it]
  131. X
  132. X-----------------------------------------------------------------------------
  133. X
  134. XGo to /sys/i386/conf and type
  135. X    config YOUR_MACHINE_NAME
  136. Xthen go to /sys/compile/YOUR_MACHINE_NAME and type
  137. X    make depend
  138. X    make
  139. X
  140. END-of-install.bsd
  141. echo x - spkr.7
  142. sed 's/^X//' >spkr.7 << 'END-of-spkr.7'
  143. X.TH SPKR 7
  144. X.SH NAME
  145. Xspkr \- console speaker device driver
  146. X.SH DESCRIPTION
  147. XThe speaker device driver allows applications to control the PC console
  148. Xspeaker on an IBM-PC-compatible machine running UNIX.
  149. X.PP
  150. XOnly one process may have this device open at any given time; open() and
  151. Xclose() are used to lock and relinquish it. An attempt to open() when
  152. Xanother process has the device locked will return -1 with an EBUSY error
  153. Xindication. Writes to the device are interpreted as 'play strings' in a
  154. Xsimple ASCII melody notation. An ioctl() for tone generation at arbitrary
  155. Xfrequencies is also supported.
  156. X.PP
  157. XSound-generation does \fInot\fR monopolize the processor; in fact, the driver
  158. Xspends most of its time sleeping while the PC hardware is emitting
  159. Xtones. Other processes may emit beeps while the driver is running.
  160. X.PP
  161. XApplications may call ioctl() on a speaker file descriptor to control the
  162. Xspeaker driver directly; definitions for the ioctl() interface are in
  163. Xsys/spkr.h. The tone_t structure used in these calls has two fields,
  164. Xspecifying a frequency (in hz) and a duration (in 1/100ths of a second).
  165. XA frequency of zero is interpreted as a rest.
  166. X.PP
  167. XAt present there are two such ioctls. SPKRTONE accepts a pointer to a
  168. Xsingle tone structure as third argument and plays it. SPKRTUNE accepts a
  169. Xpointer to the first of an array of tone structures and plays them in
  170. Xcontinuous sequence; this array must be terminated by a final member with
  171. Xa zero duration.
  172. X.PP
  173. XThe play-string language is modelled on the PLAY statement conventions of
  174. XIBM BASIC 2.0. The MB, MF and X primitives of PLAY are not useful in a UNIX 
  175. Xenvironment and are omitted. The `octave-tracking' feature is also new.
  176. X.PP
  177. XThere are 84 accessible notes numbered 1-83 in 7 octaves, each running from
  178. XC to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts
  179. Xwith middle C. By default, the play function emits half-second notes with the
  180. Xlast 1/16th second being `rest time'.
  181. X.PP
  182. XPlay strings are interpreted left to right as a series of play command groups;
  183. Xletter case is ignored. Play command groups are as follows:
  184. X.PP
  185. XCDEFGAB -- letters A through G cause the corresponding note to be played in the
  186. Xcurrent octave. A note letter may optionally be followed by an \fIaccidental
  187. Xsign\fR, one of # + or -; the first two of these cause it to be sharped one
  188. Xhalf-tone, the last causes it to be flatted one half-tone. It may also be
  189. Xfollowed by a time value number and by sustain dots (see below). Time values
  190. Xare interpreted as for the L command below;.
  191. X.PP
  192. XO <n> -- if <n> is numeric, this sets the current octave. <n> may also be one
  193. Xof 'L' or 'N' to enable or disable octave-tracking (it is disabled by default).
  194. XWhen octave-tracking is on, interpretation of a pair of letter notes will
  195. Xchange octaves if necessary in order to make the smallest possible jump between
  196. Xnotes. Thus "olbc" will be played as "olb>c", and "olcb" as "olc<b". Octave
  197. Xlocking is disabled for one letter note following by >, < and O[0123456].
  198. X.PP
  199. X> -- bump the current octave up one.
  200. X.PP
  201. X< -- drop the current octave down one.
  202. X.PP
  203. XN <n> -- play note n, n being 1 to 84 or 0 for a rest of current time value.
  204. XMay be followedv by sustain dots.
  205. X.PP
  206. XL <n> -- sets the current time value for notes. The default is L4, quarter
  207. Xnotes. The lowest possible value is 1; values up to 64 are accepted. L1 sets
  208. Xwhole notes, L2 sets half notes, L4 sets quarter notes, etc..
  209. X.PP
  210. XP <n> -- pause (rest), with <n> interpreted as for L. May be followed by
  211. Xsustain dots. May also be written '~'.
  212. X.PP
  213. XT <n> -- Sets the number of quarter notes per minute; default is 120. Musical
  214. Xnames for common tempi are:
  215. X
  216. X.TS
  217. Xa a a.
  218. X            Tempo        Beats Per Minute
  219. Xvery slow    Larghissimo    
  220. X            Largo        40-60
  221. X             Larghetto        60-66
  222. X            Grave           
  223. X            Lento           
  224. X            Adagio           66-76
  225. Xslow        Adagietto        
  226. X            Andante       76-108
  227. Xmedium       Andantino    
  228. X            Moderato    108-120
  229. Xfast        Allegretto    
  230. X            Allegro       120-168
  231. X            Vivace        
  232. X            Veloce        
  233. X            Presto        168-208
  234. Xvery fast    Prestissimo    
  235. X.TE
  236. X.PP
  237. XM[LNS] -- set articulation. MN (N for normal) is the default; the last 1/8th of
  238. Xthe note's value is rest time. You can set ML for legato (no rest space) or
  239. XMS (staccato) 1/4 rest space.
  240. X.PP
  241. XNotes (that is, CDEFGAB or N command character groups) may be followed by
  242. Xsustain dots. Each dot causes the note's value to be lengthened by one-half
  243. Xfor each one. Thus, a note dotted once is held for 3/2 of its undotted value;
  244. Xdotted twice, it is held 9/4, and three times would give 27/8. 
  245. X.PP
  246. XWhitespace in play strings is simply skipped and may be used to separate
  247. Xmelody sections.
  248. X.SH BUGS
  249. XDue to roundoff in the pitch tables and slop in the tone-generation and timer
  250. Xhardware (neither of which was designed for precision), neither pitch accuracy
  251. Xnor timings will be mathematically exact. There is no volume control.
  252. X.PP
  253. XIn play strings which are very long (longer than your system's physical I/O
  254. Xblocks) note suffixes or numbers may occasionally be parsed incorrectly due
  255. Xto crossing a block boundary.
  256. X.SH FILES
  257. X/dev/speaker -- speaker device file
  258. X.SH AUTHOR
  259. XEric S. Raymond (esr@snark.thyrsus.com) Feb 1990
  260. END-of-spkr.7
  261. echo x - Makefile
  262. sed 's/^X//' >Makefile << 'END-of-Makefile'
  263. X#
  264. X# Speaker driver package makefile
  265. X#
  266. XCFLAGS = -I. -O # -DDEBUG
  267. XLDFLAGS = -s
  268. X
  269. Xall: Driver.o
  270. X
  271. Xinstall:
  272. X    ./Install
  273. X
  274. XDriver.o: spkr.c
  275. X    $(CC) $(CFLAGS) -c spkr.c
  276. X    mv spkr.o Driver.o
  277. X
  278. Xclean:
  279. X    rm -f Driver.o *~ speaker.shar
  280. X
  281. XDSP =  Files Install Master Name Node Remove Size System 
  282. Xshar:
  283. X    shar READ.ME install.bsd spkr.7 Makefile spkr.[ch] \
  284. X        interp.c $(DSP) playtest >speaker.shar
  285. END-of-Makefile
  286. echo x - spkr.c
  287. sed 's/^X//' >spkr.c << 'END-of-spkr.c'
  288. X/*
  289. X * spkr.c -- device driver for console speaker on 80386
  290. X *
  291. X * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
  292. X *      modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
  293. X */
  294. X
  295. X#ifdef __386BSD__
  296. X#include "speaker.h"
  297. X#endif
  298. X#if !defined(__386BSD__) || (NSPEAKER > 0)
  299. X
  300. X#ifdef __386BSD__
  301. X#include "types.h"
  302. X#include "param.h"
  303. X#include "errno.h"
  304. X#include "buf.h"
  305. X#include "uio.h"
  306. X
  307. X#define CADDR caddr_t
  308. X#define err_ret(x) return(x)
  309. X#else /* SYSV */
  310. X#include <sys/types.h>
  311. X#include <sys/param.h>
  312. X#include <sys/dir.h>
  313. X#include <sys/signal.h>
  314. X#include <sys/errno.h>
  315. X#include <sys/ioctl.h>
  316. X#include <sys/user.h>
  317. X#include <sys/sysmacros.h> 
  318. X#include <limits.h>
  319. X
  320. X#define CADDR char *
  321. X#define err_ret(x) u.u_error = (x)
  322. X#endif
  323. X
  324. X#include "spkr.h"
  325. X
  326. X/**************** MACHINE DEPENDENT PART STARTS HERE *************************
  327. X *
  328. X * This section defines a function tone() which causes a tone of given
  329. X * frequency and duration from the 80x86's console speaker.
  330. X * Another function endtone() is defined to force sound off, and there is
  331. X * also a rest() entry point to do pauses.
  332. X *
  333. X * Audible sound is generated using the Programmable Interval Timer (PIT) and
  334. X * Programmable Peripheral Interface (PPI) attached to the 80x86's speaker. The
  335. X * PPI controls whether sound is passed through at all; the PIT's channel 2 is
  336. X * used to generate clicks (a square wave) of whatever frequency is desired.
  337. X *
  338. X * The non-BSD code requires SVr3.2-compatible inb(), outb(), timeout(),
  339. X * sleep(), and wakeup().
  340. X */
  341. X
  342. X/*
  343. X * PIT and PPI port addresses and control values
  344. X *
  345. X * Most of the magic is hidden in the TIMER_PREP value, which selects PIT
  346. X * channel 2, frequency LSB first, square-wave mode and binary encoding.
  347. X * The encoding is as follows:
  348. X *
  349. X * +----------+----------+---------------+-----+
  350. X * |  1    0  |  1    1  |  0    1    1  |  0  |
  351. X * | SC1  SC0 | RW1  RW0 | M2   M1   M0  | BCD |
  352. X * +----------+----------+---------------+-----+
  353. X *   Counter     Write        Mode 3      Binary
  354. X *  Channel 2  LSB first,  (Square Wave) Encoding 
  355. X *             MSB second
  356. X */
  357. X#define PPI        0x61    /* port of Programmable Peripheral Interface */
  358. X#define PPI_SPKR    0x03    /* turn these PPI bits on to pass sound */
  359. X#define PIT_CTRL    0x43    /* PIT control address */
  360. X#define PIT_COUNT    0x42    /* PIT count address */
  361. X#define PIT_MODE    0xB6    /* set timer mode for sound generation */
  362. X
  363. X/*
  364. X * Magic numbers for timer control. 
  365. X */
  366. X#define TIMER_CLK    1193180L    /* corresponds to 18.2 MHz tick rate */
  367. X
  368. Xstatic int endtone()
  369. X/* turn off the speaker, ending current tone */
  370. X{
  371. X    wakeup((CADDR)endtone);
  372. X    outb(PPI, inb(PPI) & ~PPI_SPKR);
  373. X}
  374. X
  375. Xstatic void tone(hz, ticks)
  376. X/* emit tone of frequency hz for given number of ticks */
  377. Xunsigned int hz, ticks;
  378. X{
  379. X    unsigned int divisor = TIMER_CLK / hz;
  380. X    int sps;
  381. X
  382. X#ifdef DEBUG
  383. X    printf("tone: hz=%d ticks=%d\n", hz, ticks);
  384. X#endif /* DEBUG */
  385. X
  386. X    /* set timer to generate clicks at given frequency in Hertz */
  387. X#ifdef __386BSD__
  388. X    sps = spltty();
  389. X#else
  390. X    sps = spl5();
  391. X#endif
  392. X    outb(PIT_CTRL, PIT_MODE);        /* prepare timer */
  393. X    outb(PIT_COUNT, (unsigned char) divisor);  /* send lo byte */
  394. X    outb(PIT_COUNT, (divisor >> 8));    /* send hi byte */
  395. X    splx(sps);
  396. X
  397. X    /* turn the speaker on */
  398. X    outb(PPI, inb(PPI) | PPI_SPKR);
  399. X
  400. X    /*
  401. X     * Set timeout to endtone function, then give up the timeslice.
  402. X     * This is so other processes can execute while the tone is being
  403. X     * emitted.
  404. X     */
  405. X    timeout((CADDR)endtone, (CADDR)NULL, ticks);
  406. X    sleep((CADDR)endtone, PZERO - 1);
  407. X}
  408. X
  409. Xstatic int endrest()
  410. X/* end a rest */
  411. X{
  412. X    wakeup((CADDR)endrest);
  413. X}
  414. X
  415. Xstatic void rest(ticks)
  416. X/* rest for given number of ticks */
  417. Xint    ticks;
  418. X{
  419. X    /*
  420. X     * Set timeout to endrest function, then give up the timeslice.
  421. X     * This is so other processes can execute while the rest is being
  422. X     * waited out.
  423. X     */
  424. X#ifdef DEBUG
  425. X    printf("rest: %d\n", ticks);
  426. X#endif /* DEBUG */
  427. X    timeout((CADDR)endrest, (CADDR)NULL, ticks);
  428. X    sleep((CADDR)endrest, PZERO - 1);
  429. X}
  430. X
  431. X#include "interp.c"    /* playinit() and playstring() */
  432. X
  433. X/******************* UNIX DRIVER HOOKS BEGIN HERE **************************
  434. X *
  435. X * This section implements driver hooks to run playstring() and the tone(),
  436. X * endtone(), and rest() functions defined above.  For non-BSD systems,
  437. X * SVr3.2-compatible copyin() is also required.
  438. X */
  439. X
  440. Xstatic int spkr_active;    /* exclusion flag */
  441. X#ifdef __386BSD__
  442. Xstatic struct  buf *spkr_inbuf; /* incoming buf */
  443. X#endif
  444. X
  445. Xint spkropen(dev)
  446. Xdev_t    dev;
  447. X{
  448. X#ifdef DEBUG
  449. X    printf("spkropen: entering with dev = %x\n", dev);
  450. X#endif /* DEBUG */
  451. X
  452. X    if (minor(dev) != 0)
  453. X    err_ret(ENXIO);
  454. X    else if (spkr_active)
  455. X    err_ret(EBUSY);
  456. X    else
  457. X    {
  458. X    playinit();
  459. X#ifdef __386BSD__
  460. X    spkr_inbuf = geteblk(DEV_BSIZE);
  461. X#endif
  462. X    spkr_active = 1;
  463. X    }
  464. X#ifdef __386BSD__
  465. X    return(0);
  466. X#endif
  467. X}
  468. X
  469. X#ifdef __386BSD__
  470. Xint spkrwrite(dev, uio)
  471. Xstruct uio *uio;
  472. X#else
  473. Xint spkrwrite(dev)
  474. X#endif
  475. Xdev_t    dev;
  476. X{
  477. X#ifdef __386BSD__
  478. X    register unsigned n;
  479. X    char *cp;
  480. X    int error;
  481. X#endif
  482. X#ifdef DEBUG
  483. X#ifdef __386BSD__
  484. X    printf("spkrwrite: entering with dev = %x, count = %d\n",
  485. X        dev, uio->uio_resid);
  486. X#else
  487. X    printf("spkrwrite: entering with dev = %x, u.u_count = %d\n",
  488. X        dev, u.u_count);
  489. X#endif
  490. X#endif /* DEBUG */
  491. X
  492. X    if (minor(dev) != 0)
  493. X    err_ret(ENXIO);
  494. X    else
  495. X    {
  496. X#ifdef __386BSD__
  497. X    n = MIN(DEV_BSIZE, uio->uio_resid);
  498. X    cp = spkr_inbuf->b_un.b_addr;
  499. X    error = uiomove(cp, n, uio);
  500. X    if (!error)
  501. X        playstring(cp, n);
  502. X    return(error);
  503. X#else
  504. X    char    bfr[STD_BLK];
  505. X
  506. X    copyin(u.u_base, bfr, u.u_count);
  507. X    playstring(bfr, u.u_count);
  508. X    u.u_base += u.u_count;
  509. X    u.u_count = 0;
  510. X#endif
  511. X    }
  512. X}
  513. X
  514. Xint spkrclose(dev)
  515. Xdev_t    dev;
  516. X{
  517. X#ifdef DEBUG
  518. X    printf("spkrclose: entering with dev = %x\n", dev);
  519. X#endif /* DEBUG */
  520. X
  521. X    if (minor(dev) != 0)
  522. X    err_ret(ENXIO);
  523. X    else
  524. X    {
  525. X    endtone();
  526. X#ifdef __386BSD__
  527. X    brelse(spkr_inbuf);
  528. X#endif
  529. X    spkr_active = 0;
  530. X    }
  531. X#ifdef __386BSD__
  532. X    return(0);
  533. X#endif
  534. X}
  535. X
  536. Xint spkrioctl(dev, cmd, cmdarg)
  537. Xdev_t    dev;
  538. Xint    cmd;
  539. XCADDR   cmdarg;
  540. X{
  541. X#ifdef DEBUG
  542. X    printf("spkrioctl: entering with dev = %x, cmd = %x\n", dev, cmd);
  543. X#endif /* DEBUG */
  544. X
  545. X    if (minor(dev) != 0)
  546. X    err_ret(ENXIO);
  547. X    else if (cmd == SPKRTONE)
  548. X    {
  549. X    tone_t    *tp = (tone_t *)cmdarg;
  550. X
  551. X    if (tp->frequency == 0)
  552. X        rest(tp->duration);
  553. X    else
  554. X        tone(tp->frequency, tp->duration);
  555. X    }
  556. X    else if (cmd == SPKRTUNE)
  557. X    {
  558. X#ifdef __386BSD__
  559. X    tone_t  *tp = (tone_t *)(*(caddr_t *)cmdarg);
  560. X    tone_t ttp;
  561. X    int error;
  562. X
  563. X    for (; ; tp++) {
  564. X        error = copyin(tp, &ttp, sizeof(tone_t));
  565. X        if (error)
  566. X            return(error);
  567. X        if (ttp.duration == 0)
  568. X            break;
  569. X        if (ttp.frequency == 0)
  570. X        rest(ttp.duration);
  571. X        else
  572. X        tone(ttp.frequency, ttp.duration);
  573. X    }
  574. X#else
  575. X    tone_t    *tp = (tone_t *)cmdarg;
  576. X
  577. X    for (; tp->duration; tp++)
  578. X        if (tp->frequency == 0)
  579. X        rest(tp->duration);
  580. X        else
  581. X        tone(tp->frequency, tp->duration);
  582. X#endif
  583. X    }
  584. X    else
  585. X    err_ret(EINVAL);
  586. X#ifdef __386BSD__
  587. X    return(0);
  588. X#endif
  589. X}
  590. X
  591. X#endif  /* !defined(__386BSD__) || (NSPEAKER > 0) */
  592. X/* spkr.c ends here */
  593. END-of-spkr.c
  594. echo x - spkr.h
  595. sed 's/^X//' >spkr.h << 'END-of-spkr.h'
  596. X/*
  597. X * spkr.h -- interface definitions for speaker ioctl()
  598. X *
  599. X * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
  600. X *      modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
  601. X */
  602. X
  603. X#ifndef _SPKR_H_
  604. X#define _SPKR_H_
  605. X
  606. X#ifdef __386BSD__
  607. X#ifndef KERNEL
  608. X#include <sys/ioctl.h>
  609. X#else
  610. X#include "ioctl.h"
  611. X#endif
  612. X
  613. X#define SPKRTONE        _IOW('S', 1, tone_t)    /* emit tone */
  614. X#define SPKRTUNE        _IO('S', 2)             /* emit tone sequence*/
  615. X#else /* SYSV */
  616. X#define    SPKRIOC        ('S'<<8)
  617. X#define    SPKRTONE    (SPKRIOC|1)    /* emit tone */
  618. X#define    SPKRTUNE    (SPKRIOC|2)    /* emit tone sequence*/
  619. X#endif
  620. X
  621. Xtypedef struct
  622. X{
  623. X    int    frequency;    /* in hertz */
  624. X    int duration;    /* in 1/100ths of a second */
  625. X}
  626. Xtone_t;
  627. X
  628. X#endif /* _SPKR_H_ */
  629. X/* spkr.h ends here */
  630. END-of-spkr.h
  631. echo x - interp.c
  632. sed 's/^X//' >interp.c << 'END-of-interp.c'
  633. X/*
  634. X * interp.c -- device driver for console speaker on 80386
  635. X *
  636. X * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
  637. X *
  638. X * this is the part of the code common to all 386 UNIX OSes
  639. X *
  640. X * playinit() and playstring() are called from the appropriate driver
  641. X */
  642. X
  643. X#ifdef __386BSD__
  644. X#include "param.h"
  645. X#else
  646. X#include <sys/param.h>
  647. X#endif
  648. X
  649. X#ifndef HZ
  650. X#define HZ 60
  651. X#endif
  652. X
  653. X
  654. X/**************** PLAY STRING INTERPRETER BEGINS HERE **********************
  655. X *
  656. X * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement;
  657. X * M[LNS] are missing and the ~ synonym and octave-tracking facility is added.
  658. X * Requires tone(), rest(), and endtone(). String play is not interruptible
  659. X * except possibly at physical block boundaries.
  660. X */
  661. X
  662. Xtypedef int    bool;
  663. X#define TRUE    1
  664. X#define FALSE    0
  665. X
  666. X#define toupper(c)    ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z')))
  667. X#define isdigit(c)    (((c) >= '0') && ((c) <= '9'))
  668. X#define dtoi(c)        ((c) - '0')
  669. X
  670. Xstatic int octave;    /* currently selected octave */
  671. Xstatic int whole;    /* whole-note time at current tempo, in ticks */
  672. Xstatic int value;    /* whole divisor for note time, quarter note = 1 */
  673. Xstatic int fill;    /* controls spacing of notes */
  674. Xstatic bool octtrack;    /* octave-tracking on? */
  675. Xstatic bool octprefix;    /* override current octave-tracking state? */
  676. X
  677. X/*
  678. X * Magic number avoidance...
  679. X */
  680. X#define SECS_PER_MIN    60    /* seconds per minute */
  681. X#define WHOLE_NOTE    4    /* quarter notes per whole note */
  682. X#define MIN_VALUE    64    /* the most we can divide a note by */
  683. X#define DFLT_VALUE    4    /* default value (quarter-note) */
  684. X#define FILLTIME    8    /* for articulation, break note in parts */
  685. X#define STACCATO    6    /* 6/8 = 3/4 of note is filled */
  686. X#define NORMAL        7    /* 7/8ths of note interval is filled */
  687. X#define LEGATO        8    /* all of note interval is filled */
  688. X#define DFLT_OCTAVE    4    /* default octave */
  689. X#define MIN_TEMPO    32    /* minimum tempo */
  690. X#define DFLT_TEMPO    120    /* default tempo */
  691. X#define MAX_TEMPO    255    /* max tempo */
  692. X#define NUM_MULT    3    /* numerator of dot multiplier */
  693. X#define DENOM_MULT    2    /* denominator of dot multiplier */
  694. X
  695. X/* letter to half-tone:  A   B  C  D  E  F  G */
  696. Xstatic int notetab[8] = {9, 11, 0, 2, 4, 5, 7};
  697. X
  698. X/*
  699. X * This is the American Standard A440 Equal-Tempered scale with frequencies
  700. X * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook...
  701. X * our octave 0 is standard octave 2.
  702. X */
  703. X#define OCTAVE_NOTES    12    /* semitones per octave */
  704. Xstatic int pitchtab[] =
  705. X{
  706. X/*        C     C#    D     D#    E     F     F#    G     G#    A     A#    B*/
  707. X/* 0 */   65,   69,   73,   78,   82,   87,   93,   98,  103,  110,  117,  123,
  708. X/* 1 */  131,  139,  147,  156,  165,  175,  185,  196,  208,  220,  233,  247,
  709. X/* 2 */  262,  277,  294,  311,  330,  349,  370,  392,  415,  440,  466,  494,
  710. X/* 3 */  523,  554,  587,  622,  659,  698,  740,  784,  831,  880,  932,  988,
  711. X/* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
  712. X/* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
  713. X/* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
  714. X};
  715. X
  716. Xstatic void playinit()
  717. X{
  718. X    octave = DFLT_OCTAVE;
  719. X    whole = (HZ * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
  720. X    fill = NORMAL;
  721. X    value = DFLT_VALUE;
  722. X    octtrack = FALSE;
  723. X    octprefix = TRUE;    /* act as though there was an initial O(n) */
  724. X}
  725. X
  726. Xstatic void playtone(pitch, value, sustain)
  727. X/* play tone of proper duration for current rhythm signature */
  728. Xint    pitch, value, sustain;
  729. X{
  730. X    register int    sound, silence, snum = 1, sdenom = 1;
  731. X
  732. X    /* this weirdness avoids floating-point arithmetic */
  733. X    for (; sustain; sustain--)
  734. X    {
  735. X    snum *= NUM_MULT;
  736. X    sdenom *= DENOM_MULT;
  737. X    }
  738. X
  739. X    if (pitch == -1)
  740. X    rest(whole * snum / (value * sdenom));
  741. X    else
  742. X    {
  743. X    sound = (whole * snum) / (value * sdenom)
  744. X        - (whole * (FILLTIME - fill)) / (value * FILLTIME);
  745. X    silence = whole * (FILLTIME-fill) * snum / (FILLTIME * value * sdenom);
  746. X
  747. X#ifdef DEBUG
  748. X    printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
  749. X            pitch, sound, silence);
  750. X#endif /* DEBUG */
  751. X
  752. X    tone(pitchtab[pitch], sound);
  753. X    if (fill != LEGATO)
  754. X        rest(silence);
  755. X    }
  756. X}
  757. X
  758. Xstatic int abs(n)
  759. Xint n;
  760. X{
  761. X    if (n < 0)
  762. X    return(-n);
  763. X    else
  764. X    return(n);
  765. X}
  766. X
  767. Xstatic void playstring(cp, slen)
  768. X/* interpret and play an item from a notation string */
  769. Xchar    *cp;
  770. Xsize_t    slen;
  771. X{
  772. X    int        pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
  773. X
  774. X#define GETNUM(cp, v)    for(v=0; isdigit(cp[1]) && slen > 0; ) \
  775. X                {v = v * 10 + (*++cp - '0'); slen--;}
  776. X    for (; slen--; cp++)
  777. X    {
  778. X    int        sustain, timeval, tempo;
  779. X    register char    c = toupper(*cp);
  780. X
  781. X#ifdef DEBUG
  782. X    printf("playstring: %c (%x)\n", c, c);
  783. X#endif /* DEBUG */
  784. X
  785. X    switch (c)
  786. X    {
  787. X    case 'A':  case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  788. X
  789. X        /* compute pitch */
  790. X        pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
  791. X
  792. X        /* this may be followed by an accidental sign */
  793. X        if (cp[1] == '#' || cp[1] == '+')
  794. X        {
  795. X        ++pitch;
  796. X        ++cp;
  797. X        slen--;
  798. X        }
  799. X        else if (cp[1] == '-')
  800. X        {
  801. X        --pitch;
  802. X        ++cp;
  803. X        slen--;
  804. X        }
  805. X
  806. X        /*
  807. X         * If octave-tracking mode is on, and there has been no octave-
  808. X         * setting prefix, find the version of the current letter note
  809. X         * closest to the last regardless of octave.
  810. X         */
  811. X        if (octtrack && !octprefix)
  812. X        {
  813. X        if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES-lastpitch))
  814. X        {
  815. X            ++octave;
  816. X            pitch += OCTAVE_NOTES;
  817. X        }
  818. X
  819. X        if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES)-lastpitch))
  820. X        {
  821. X            --octave;
  822. X            pitch -= OCTAVE_NOTES;
  823. X        }
  824. X        }
  825. X        octprefix = FALSE;
  826. X        lastpitch = pitch;
  827. X
  828. X        /* ...which may in turn be followed by an override time value */
  829. X        GETNUM(cp, timeval);
  830. X        if (timeval <= 0 || timeval > MIN_VALUE)
  831. X        timeval = value;
  832. X
  833. X        /* ...and/or sustain dots */
  834. X        for (sustain = 0; cp[1] == '.'; cp++)
  835. X        {
  836. X        slen--;
  837. X        sustain++;
  838. X        }
  839. X
  840. X        /* time to emit the actual tone */
  841. X        playtone(pitch, timeval, sustain);
  842. X        break;
  843. X
  844. X    case 'O':
  845. X        if (cp[1] == 'N' || cp[1] == 'n')
  846. X        {
  847. X        octprefix = octtrack = FALSE;
  848. X        ++cp;
  849. X        slen--;
  850. X        }
  851. X        else if (cp[1] == 'L' || cp[1] == 'l')
  852. X        {
  853. X        octtrack = TRUE;
  854. X        ++cp;
  855. X        slen--;
  856. X        }
  857. X        else
  858. X        {
  859. X        GETNUM(cp, octave);
  860. X        if (octave >= sizeof(pitchtab) / OCTAVE_NOTES)
  861. X            octave = DFLT_OCTAVE;
  862. X        octprefix = TRUE;
  863. X        }
  864. X        break;
  865. X
  866. X    case '>':
  867. X        if (octave < sizeof(pitchtab) / OCTAVE_NOTES - 1)
  868. X        octave++;
  869. X        octprefix = TRUE;
  870. X        break;
  871. X
  872. X    case '<':
  873. X        if (octave > 0)
  874. X        octave--;
  875. X        octprefix = TRUE;
  876. X        break;
  877. X
  878. X    case 'N':
  879. X        GETNUM(cp, pitch);
  880. X        for (sustain = 0; cp[1] == '.'; cp++)
  881. X        {
  882. X        slen--;
  883. X        sustain++;
  884. X        }
  885. X        playtone(pitch - 1, value, sustain);
  886. X        break;
  887. X
  888. X    case 'L':
  889. X        GETNUM(cp, value);
  890. X        if (value <= 0 || value > MIN_VALUE)
  891. X        value = DFLT_VALUE;
  892. X        break;
  893. X
  894. X    case 'P':
  895. X    case '~':
  896. X        /* this may be followed by an override time value */
  897. X        GETNUM(cp, timeval);
  898. X        if (timeval <= 0 || timeval > MIN_VALUE)
  899. X        timeval = value;
  900. X        for (sustain = 0; cp[1] == '.'; cp++)
  901. X        {
  902. X        slen--;
  903. X        sustain++;
  904. X        }
  905. X        playtone(-1, timeval, sustain);
  906. X        break;
  907. X
  908. X    case 'T':
  909. X        GETNUM(cp, tempo);
  910. X        if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
  911. X        tempo = DFLT_TEMPO;
  912. X        whole = (HZ * SECS_PER_MIN * WHOLE_NOTE) / tempo;
  913. X        break;
  914. X
  915. X    case 'M':
  916. X        if (cp[1] == 'N' || cp[1] == 'n')
  917. X        {
  918. X        fill = NORMAL;
  919. X        ++cp;
  920. X        slen--;
  921. X        }
  922. X        else if (cp[1] == 'L' || cp[1] == 'l')
  923. X        {
  924. X        fill = LEGATO;
  925. X        ++cp;
  926. X        slen--;
  927. X        }
  928. X        else if (cp[1] == 'S' || cp[1] == 's')
  929. X        {
  930. X        fill = STACCATO;
  931. X        ++cp;
  932. X        slen--;
  933. X        }
  934. X        break;
  935. X    }
  936. X    }
  937. X}
  938. END-of-interp.c
  939. echo x - Files
  940. sed 's/^X//' >Files << 'END-of-Files'
  941. X/usr/include/sys/spkr.h
  942. END-of-Files
  943. echo x - Install
  944. sed 's/^X//' >Install << 'END-of-Install'
  945. X#
  946. X# Speaker driver installation script
  947. X#
  948. XTMP=/tmp/speaker.err
  949. XERR1=" Errors have been written to the file $TMP."
  950. XERR2=" The Speaker Driver software was not installed."
  951. X
  952. Xecho "Installing Speaker Driver Software Package"
  953. X
  954. X/etc/conf/bin/idcheck -p speaker 2>$TMP
  955. Xif [ $? != 0 ]
  956. Xthen
  957. X    echo "The speaker package is already at least partly installed.
  958. X    Removing the old version now..."
  959. X    /etc/conf/bin/idinstall -d speaker
  960. Xfi
  961. X
  962. X/etc/conf/bin/idinstall -a -k speaker 2>>$TMP
  963. Xif [ $? != 0 ]
  964. Xthen
  965. X    message "There was an error during package installation. $ERR1 $ERR2"
  966. X    exit 1
  967. Xfi
  968. X
  969. X/etc/conf/bin/idbuild 2>>$TMP
  970. Xif [ $? != 0 ]
  971. Xthen
  972. X    message "There was an error during kernel reconfiguration. $ERR1 $ERR2"
  973. X    exit 1
  974. Xfi
  975. X
  976. Xrm -f $TMP
  977. X
  978. Xcp spkr.h /usr/include/sys/spkr.h
  979. X
  980. Xecho "Performing shutdown..."
  981. Xcd /; exec /etc/shutdown -g0 -y
  982. END-of-Install
  983. echo x - Master
  984. sed 's/^X//' >Master << 'END-of-Master'
  985. Xspeaker    ocwi    iocH    spkr    0    0    1    1    -1
  986. END-of-Master
  987. echo x - Name
  988. sed 's/^X//' >Name << 'END-of-Name'
  989. X386 UNIX Speaker Device Driver Package
  990. END-of-Name
  991. echo x - Node
  992. sed 's/^X//' >Node << 'END-of-Node'
  993. Xspeaker    speaker    c    0
  994. END-of-Node
  995. echo x - Remove
  996. sed 's/^X//' >Remove << 'END-of-Remove'
  997. X#
  998. X# Speaker driver remove script
  999. X#
  1000. XTMP=/tmp/speaker.err
  1001. XRERR="Errors have been written to the file $TMP."
  1002. X
  1003. Xecho "Removing Speaker Driver Software Package"
  1004. X
  1005. X/etc/conf/bin/idinstall -d speaker 2>$TMP
  1006. Xif [ $? != 0 ]
  1007. Xthen
  1008. X    message "There was an error during package removal. $RERR"
  1009. X    exit 1
  1010. Xfi
  1011. X
  1012. X/etc/conf/bin/idbuild 2>>$TMP
  1013. Xif [ $? != 0 ]
  1014. Xthen
  1015. X    message "There was an error during kernel reconfiguration. $RERR"
  1016. X    exit 1
  1017. Xfi
  1018. X
  1019. Xrm -f /dev/speaker $TMP /usr/include/sys/spkr.h
  1020. X
  1021. Xexit 0
  1022. END-of-Remove
  1023. echo x - Size
  1024. sed 's/^X//' >Size << 'END-of-Size'
  1025. XROOT=1400
  1026. XUSR=100
  1027. END-of-Size
  1028. echo x - System
  1029. sed 's/^X//' >System << 'END-of-System'
  1030. Xspeaker    Y    1    0    0    0    0    0    0    0
  1031. END-of-System
  1032. echo x - playtest
  1033. sed 's/^X//' >playtest << 'END-of-playtest'
  1034. X:
  1035. X# Test script for the speaker driver
  1036. X#
  1037. X# v1.0 by Eric S. Raymond (Feb 1990)
  1038. X#      modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
  1039. X#
  1040. Xreveille="t255l8c.f.afc~c.f.afc~c.f.afc.f.a..f.~c.f.afc~c.f.afc~c.f.afc~c.f.."
  1041. Xcontact="<cd<a#~<a#>f"
  1042. Xdance="t240<cfcfgagaa#b#>dc<a#a.~fg.gaa#.agagegc.~cfcfgagaa#b#>dc<a#a.~fg.gga.agfgfgf."
  1043. Xloony="t255cf8f8edc<a.>~cf8f8edd#e.~ce8cdce8cd.<a>c8c8c#def8af8."
  1044. X
  1045. Xcase $1 in
  1046. Xreveille) echo  $reveille >/dev/speaker;;
  1047. Xcontact)  echo  $contact >/dev/speaker;;
  1048. Xdance)  echo  $dance >/dev/speaker;;
  1049. Xloony)  echo  $loony >/dev/speaker;;
  1050. X*)
  1051. X    echo "No such tune. Available tunes are:"
  1052. X    echo
  1053. X    echo "reveille -- Reveille"
  1054. X    echo "contact -- Contact theme from Close Encounters"
  1055. X    echo "dance -- Lord of the Dance (aka Simple Gifts)"
  1056. X    echo "loony -- Loony Toons theme"
  1057. X    ;;
  1058. Xesac
  1059. END-of-playtest
  1060. exit
  1061.